iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
Software Development

輕鬆學習設計模式Design Pattern系列 第 20

Day 20 解釋器模式 Interpreter Pattern

  • 分享至 

  • xImage
  •  

大家有沒有想過當你在終端機輸入指令時,電腦是如何理解並執行這些指令的?或者當你使用正則表達式搜尋文字時,背後的機制是什麼?這些看似神奇的功能背後,其實都隱藏著一個強大而優雅的設計模式,那就是解釋器模式 Interpreter Pattern,今天就來聊聊這個模式,幫助我們理解當電腦「讀懂」我們的指令時背後的魔法。

什麼是解釋器模式?

解釋器模式是一種行為型設計模式,主要用來解析語言、處理簡單語法規則的。這個模式背後的想法其實很簡單:我們定義一套「語法規則」,然後讓每個「字元」或「符號」有自己專屬的解釋方式。這樣我們就能依照語法,逐步分析出我們想要的結果。

打個比方,就像我們學習一種新語言時,會先學習單字,接著組合句子,最後可以用來進行溝通。解釋器模式就像是這個過程的數位版,先定義每個「單字」的意思,再教你如何解釋這些字。

解釋器模式在計算機中的應用

計算機應該是最能體現解釋器模式的例子之一。想像你有一個簡單的計算機,輸入表達式如「2 + 3 * 4」,然後計算出結果。解釋器模式就可以幫助我們將這些數字與運算符號組合成一個能夠「理解」的語法樹。

首先先定義一個 Expression 介面,它會有一個 interpret() 方法。這個方法負責對數字和符號進行解釋,

// 抽象表達式
class Expression {
public:
    virtual int interpret() = 0;
    virtual ~Expression() = default;
};

接著定義具體的 NumberExpression(數字表達式)和 OperatorExpression(運算符表達式)。數字表達式會簡單地回傳它自己的值,而運算符表達式則會對兩個子表達式進行計算,比如加法、乘法等。

// 數字表達式
class NumberExpression : public Expression {
    int number;
public:
    NumberExpression(int num) : number(num) {}
    int interpret() override {
        return number;
    }
};

// 加法表達式
class AddExpression : public Expression {
    Expression* left;
    Expression* right;
public:
    AddExpression(Expression* l, Expression* r) : left(l), right(r) {}
    int interpret() override {
        return left->interpret() + right->interpret();
    }
};

// 乘法表達式
class MultiplyExpression : public Expression {
    Expression* left;
    Expression* right;
public:
    MultiplyExpression(Expression* l, Expression* r) : left(l), right(r) {}
    int interpret() override {
        return left->interpret() * right->interpret();
    }
};

在前面已經定義了基礎的 NumberExpression、AddExpression 和 MultiplyExpression 類別。接下來我們在客戶端來實際使用這些表達式,讓整個流程完整起來。

我們會有一個解析器來遍歷表達式,並一步步解釋每個部分。假設我們要處理一個簡單的表達式「2 + 3」,客戶端的邏輯會像下面這樣:

int main() {
    // 建立一個表示數字2的NumberExpression
    Expression* num1 = new NumberExpression(2);
    
    // 建立一個表示數字3的NumberExpression
    Expression* num2 = new NumberExpression(3);
    
    // 建立一個表示加法的AddExpression,將兩個數字作為參數傳入
    Expression* addExpr = new AddExpression(num1, num2);

    int result = addExpr->interpret();
    std::cout << "2 + 3 = " << result << std::endl;

    Expression* mulExpr = new MultiplyExpression(num1, num2);
    result = mulExpr->interpret();
    std::cout << "2 * 3 = " << result << std::endl;

    // 釋放記憶體
    delete num1;
    delete num2;
    delete addExpr;
    delete mulExpr;
    
    return 0;
}

執行上述程式碼,我們會得到以下輸出,當我們將表達式「2 + 3」傳給計算機時,解釋器就會根據我們定義的語法規則一步步處理,最終給出結果。

2 + 3 = 5
2 * 3 = 6

在這個範例中,客戶端的角色就是負責將表達式拼接在一起,然後使用解釋器模式的物件來完成運算。這樣任何新加入的運算符或表達式,只需要擴展 Expression 類別,而不用改動客戶端的邏輯,保持程式的靈活性和可維護性。

解釋器模式的優缺點

說到解釋器模式的優點,它最大的魅力就在於可以輕鬆地擴展和修改語法規則。比如我們可以在不改變原有架構的情況下,輕鬆加入新的運算符號或功能,這讓解釋器模式在處理語法解析時非常靈活。

解釋器模式的缺點也很明顯。當語法規則變得越來越複雜時,類別的數量會激增,這可能導致程式碼的維護和理解變得困難。另外解釋器模式的效能並不高,尤其是當處理大規模語法時,效能的瓶頸會更加明顯。

總結

解釋器模式就像一個小型語法解析器,適合用來處理簡單的語法規則,像是計算機這樣的場景。它的擴展性讓我們可以在程式中輕鬆加入更多規則,但同時也要留意其效能和維護性。對於那些需要頻繁變更規則、處理複雜語法的情況,解釋器模式提供了一個簡潔且靈活的解決方案。

更多C++語言相關的文章,歡迎追蹤我的部落格。
https://shengyu7697.github.io/cpp-interpreter-pattern/


上一篇
Day 19 橋接模式 Bridge Pattern
下一篇
Day 21 享元模式 Flyweight Pattern
系列文
輕鬆學習設計模式Design Pattern30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言